from django_redis import get_redis_connection
from rest_framework import serializers
from goods.models import SKU
from orders.models import OrderInfo, OrderGoods
from users.models import User
from datetime import datetime
from django.db import transaction
from decimal import Decimal

class OrderSKUSerializers(serializers.ModelSerializer):
    count = serializers.IntegerField(read_only=True)
    class Meta:
        model = SKU
        fields = '__all__'

class OredrSerializers(serializers.Serializer):

    freight = serializers.DecimalField(label='运费', max_digits=10, decimal_places=2)
    skus = OrderSKUSerializers(many=True)


class SaveOrderSerializer(serializers.ModelSerializer):
    """
    下单数据序列化器
    """
    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')    # order_id需要返回的 address,pay_method前端传过来的
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True,
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }
        }
    # @transaction.atomic              使用事务的第一种形式   装饰器
    def create(self, validated_data):
        """保存订单"""
        #1,获取验证后的用户数据,地址,支付方式
        user = self.context['request'].user
        address = validated_data['address']
        pay_method = validated_data['pay_method']
        #2,生成订单编号     strftime  对时间进行格式化
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id

        #开启事务
        with transaction.atomic():                  #使用事务的第二种方式
            #创建保存点
            save_point = transaction.savepoint()

            try:
                #3,初始化生成订单基本信息表
                order = OrderInfo.objects.create(
                    order_id = order_id,
                    address = address,
                    user = user,
                    total_count=0,
                    total_amount=Decimal(0),
                    freight=Decimal(10),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID']
                )
                #4,查询选中状态的sku_id对应的sku商品

                # 建立redis连接
                conn = get_redis_connection('cart')
                # 获取选中状态的sku_id和count
                sku_id_count = conn.hgetall('cart_%s' % user.id)  # { 16:1, 15:1 }
                sku_ids = conn.smembers('cart_selected_%s' % user.id)  # {15}
                # 合并数据
                cart = {}  # {15:1}
                for sku_id in sku_ids:
                    cart[int(sku_id)] = int(sku_id_count[sku_id])
                # 查询选中状态的商品对象
                # skus = SKU.objects.filter(id__in=cart.keys())

                #5,遍历所有的sku商品
                for sku_id in sku_ids:
                    while True:
                        sku = SKU.objects.get(id = sku_id)


                        #6,获取当前sku商品对应的原始库存和销量
                        old_stock = sku.stock
                        old_sales = sku.sales
                        sku_count = cart[sku.id]
                        #7,判断购买数量是否大于库存
                        if sku_count > old_stock:
                            raise serializers.ValidationError('商品库存不足')
                        #8,如果不大于库存则修改sku商品的库存量和销量
                        # sku.stock = old_stock - sku_count
                        # sku.sales = old_sales + sku_count
                        # sku.save()
                        new_stock = old_stock - sku_count
                        new_sales = old_sales + sku_count
                        ret = SKU.objects.filter(id = sku.id,stock=old_stock).update(stock = new_stock,
                                                                               sales = new_sales)
                        if ret == 0:
                            continue

                        #9,修改spu表中的总销量
                        sku.goods.sales += sku_count
                        sku.goods.save()
                        #10,修改订单基本信息表中的总量和总价
                        order.total_amount += (sku.price * sku_count)
                        order.total_count += sku_count
                        #11,保存订单商品信息表
                        OrderGoods.objects.create(
                            order = order,
                            sku = sku,
                            count=sku_count,
                            price=sku.price,
                        )
                        break

                #累加运费
                order.total_amount += order.freight
                order.save()
            except:
                # 回滚到保存点
                transaction.savepoint_rollback(save_point)
            else:
                # 提交从保存点到当前状态的所有数据库事务操作
                transaction.savepoint_commit(save_point)
                #12,删除缓存选中状态的商品
                conn.hdel('cart_%s' % user.id, *sku_ids)
                conn.srem('cart_selected_%s' % user.id, *sku_ids)
                #13,返回结果
                return order